<template>
  <div class="workflow-design">
    <je-editor-draw
      ref="editor"
      v-model:value="value"
      v-model:language="language"
      height="100%"
      width="100%"
      :jebpm-data="jebpmData"
      :editor-xml="editorXml"
      @nodeChange="onNodeChange"
      @nodeLabelChange="onNodeLabelChange"
      @nodeRemove="onNodeRemove"
    >
      <template #bbar>
        <je-tooltip placement="top" title="保存">
          <je-button type="text" size="large" :disabled="saveDisable" @click="onSave">
            <i class="icon fal fa-save" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="保存发布">
          <je-button type="text" size="large" :disabled="saveDisable" @click="onSave('deploy')">
            <i class="icon fal fa-paper-plane" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="导入">
          <je-button type="text" size="large" @click="onImport">
            <i class="icon fal fa-file-import" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="打印">
          <je-button type="text" size="large" @click="onPrint">
            <i class="icon fal fa-print" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="原始大小">
          <je-button type="text" size="large" @click="onZoom('original')">
            <i class="icon jeicon jeicon-original-size" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="放大">
          <je-button type="text" size="large" @click="onZoom('up')">
            <i class="icon fal fa-search-plus" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="缩小">
          <je-button type="text" size="large" @click="onZoom('down')">
            <i class="icon fal fa-search-minus" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="上对齐">
          <je-button type="text" size="large" @click="onMove('top')">
            <i class="icon jeicon jeicon-align-top-s" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="右对齐">
          <je-button type="text" size="large" @click="onMove('right')">
            <i class="icon jeicon jeicon-align-right-s" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="下对齐">
          <je-button type="text" size="large" @click="onMove('bottom')">
            <i class="icon jeicon jeicon-align-bottom-s" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="左对齐">
          <je-button type="text" size="large" @click="onMove('left')">
            <i class="icon jeicon jeicon-align-left-s" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="垂直居中">
          <je-button type="text" size="large" @click="onMove('middle')">
            <i class="icon jeicon jeicon-align-center-s" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="水平居中">
          <je-button type="text" size="large" @click="onMove('center')">
            <i class="icon jeicon jeicon-align-middle-s" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="向前">
          <je-button type="text" size="large" @click="onLocation('toFront')">
            <i class="icon fal fa-send-backward" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="向后">
          <je-button type="text" size="large">
            <i class="icon fal fa-bring-forward" @click="onLocation('toBack')" />
          </je-button>
        </je-tooltip>
        <je-tooltip placement="top" title="缩略图">
          <je-button type="text" size="large" @click="onThumbnail()">
            <i class="icon jeicon jeicon-thumbnail" />
          </je-button>
        </je-tooltip>
      </template>
    </je-editor-draw>
  </div>
</template>

<script>
  import { defineComponent, ref } from 'vue';
  import { Modal, Button, Tooltip } from '@jecloud/ui';
  import EditorDraw from '../../components/editor-draw/index.js';
  import { isEmpty, isNotEmpty, encode, decode, uuid, cloneDeep } from '@jecloud/utils';
  import { doSave, doUpdateAndDeploy, getInfoById } from '@/api/index';
  import { SelectWindow } from '@jecloud/func';
  import { JE_WORKFLOWDESIGN } from '@/helper/constant';

  export default defineComponent({
    name: 'WorkflowDesign',
    components: {
      JeEditorDraw: EditorDraw,
      JeButton: Button,
      JeTooltip: Tooltip,
    },
    props: {
      jebpmData: {
        type: Object,
        default: () => {
          return {};
        },
      },
      activePanel: {
        type: Object,
        default: () => {
          return {};
        },
      },
    },
    emits: ['getActiveKey', 'loadData', 'loadGridData'],
    setup(props, { emit }) {
      //按钮数据
      const buttonArray = ref(JE_WORKFLOWDESIGN);

      const saveDisable = ref(false);

      //按钮点击方法
      const handlerBtn = (code) => {
        if (code != 'base') {
          props.jebpmData.addChildShapes({
            resourceId: code + '1',
            type: code,
            properties: { resourceId: code + '1' },
            stencil: { id: code },
          });
        }
        emit('getActiveKey', code);
      };

      //数据保存
      const onSave = (type) => {
        //切到主表单
        saveDisable.value = true;
        const cells = editor.value.$editor.graph.getModel().root.children[0].children;
        const flag = verifyWorkFlowData(cells);
        //工作流节点数据检验成功
        if (flag) {
          //进行数据组装
          props.jebpmData.dataEncapsulation(cells);

          //数据处理
          const params = getParams(props.jebpmData);

          if (type == 'deploy') {
            //保存并发布
            doUpdateAndDeploy(params)
              .then((data) => {
                const row = data.data;
                //放入组件
                props.jebpmData.setWfId(row.JE_WORKFLOW_PROCESSINFO_ID);
                saveDisable.value = false;
                Modal.notice(data.message, 'success');
                editor.value.$editor.graph.getSelectionModel().clear();
                setTimeout(() => {
                  emit('loadGridData', { key: 'base' });
                }, 100);
                doHideTooltip();
              })
              .catch((e) => {
                saveDisable.value = false;
                Modal.alert(e.message, 'error');
              });
          } else {
            //保存
            doSave(params)
              .then((data) => {
                const row = data.data;
                //放入组件
                props.jebpmData.setWfId(row.JE_WORKFLOW_PROCESSINFO_ID);
                saveDisable.value = false;
                Modal.notice(data.message, 'success');
                editor.value.$editor.graph.getSelectionModel().clear();
                setTimeout(() => {
                  emit('loadGridData', { key: 'base' });
                }, 100);
                doHideTooltip();
              })
              .catch((e) => {
                saveDisable.value = false;
                Modal.alert(e.message, 'error');
              });
          }
        } else {
          saveDisable.value = false;
        }
      };

      const editor = ref();
      const value = ref();
      const language = ref('zh_CN');

      //节点选中改变
      const onNodeChange = (nodeData) => {
        //点的画布
        if (isEmpty(nodeData)) {
          emit('getActiveKey', { key: 'base', type: 'base' });
          //点的节点
        } else {
          //节点的类型
          let nodeType = nodeData.getAttribute('type');
          // nodeData.removeType == true 说明线删除了 nodeData.edge ==true 是连线
          if (isEmpty(nodeType) && nodeData.edge && !nodeData.removeType) {
            nodeType = 'line';
            nodeData.nodeType = 'line';
          }
          if (isNotEmpty(nodeType)) {
            const nodeId = nodeData.getId();
            if (!isNaN(Number(nodeId))) {
              const resourceId = nodeType + uuid();
              nodeData.setId(resourceId);

              if (nodeType == 'task') {
                editor.value.$editor.graph.cellLabelChanged(
                  nodeData,
                  nodeData.getAttribute('name'),
                );
              }
              props.jebpmData.addChildShapes({
                resourceId: resourceId,
                type: nodeType,
                properties: {
                  resourceId: resourceId,
                  name: nodeType == 'task' ? nodeData.getAttribute('name') : '',
                },
                stencil: { id: nodeType },
                target: [{ resourceId: nodeData.target && nodeData.target.getId() }], //出口
                source: [{ resourceId: nodeData.source && nodeData.source.getId() }], //入口
              });
            }
            emit('getActiveKey', { key: nodeData.getId(), type: nodeType });
          }
        }
      };

      //修改节点的label
      const updateNodeLabel = (data) => {
        const $editor = editor.value.$editor;
        // 改变label
        const cell = $editor.graph.getSelectionCell();
        if (isNotEmpty(cell)) {
          $editor.graph.cellLabelChanged(cell, data.label);
        }
      };
      //节点label改变触发
      const onNodeLabelChange = (data, cell) => {
        //获得节点的Id
        const id = cell.getId();
        //获得节点对应表单的数据
        const nodeData = props.jebpmData.getNodeData(id);
        nodeData.properties.name = data.label;
      };

      //节点删除,删除对应的数据
      const onNodeRemove = (datas) => {
        const ids = [],
          lineNodeDatas = [];
        datas.forEach((item) => {
          ids.push(item.getId());
          if (item.nodeType == 'line' && isNotEmpty(item.source)) {
            lineNodeDatas.push({ id: item.getId(), source: item.source });
          }
        });
        if (ids.length > 0) {
          props.jebpmData.removeNodeData(ids, lineNodeDatas);
        }
      };

      //验证工作流图形是否正确
      const verifyWorkFlowData = (celss) => {
        let flag = true,
          message = '';

        const processBasicConfig = props.jebpmData.properties.processBasicConfig;
        if (
          isEmpty(processBasicConfig.name) ||
          isEmpty(processBasicConfig.funcName) ||
          /* isEmpty(processBasicConfig.contentModule) || */
          isEmpty(processBasicConfig.processClassificationName)
        ) {
          props.activePanel.doSave && props.activePanel.doSave();
          flag = false;
          message = '请填写基础配置信息！';
        }

        if (flag) {
          if (celss && celss.length > 0) {
            let startNum = 0,
              endNum = 0,
              forkNum = 0,
              joinNum = 0;
            const nodeName = [];
            for (let i = 0; i < celss.length; i++) {
              const item = celss[i];
              const nodeType = item.getAttribute('type');
              //如果type为空就是协同节点,不做处理
              if (isEmpty(nodeType)) {
                continue;
              }

              //有几个开始节点
              if (nodeType == 'start') {
                startNum++;
              }
              //有几个结束节点
              if (nodeType == 'end') {
                endNum++;
              }
              //有几个分支节点
              if (nodeType == 'branchGateway') {
                forkNum++;
              }
              //有几个聚合节点
              if (nodeType == 'aggregationGateway') {
                joinNum++;
              }

              if (!item.edge) {
                if (!item.edges) {
                  nodeName.push(item.getAttribute('name'));
                } else {
                  if (['start', 'end'].indexOf(nodeType) == -1 && item.edges.length < 2) {
                    nodeName.push(item.getAttribute('name'));
                  }
                }
              }
            }
            //流程必须仅有一个开始节点
            if (startNum != 1) {
              flag = false;
              message = '流程必须仅有一个开始节点!';
            }
            //流程必须仅有一个结束节点
            if (endNum != 1) {
              flag = false;
              message = '流程必须仅有一个结束节点!';
            }
            //分支聚合必须成对存在
            if (forkNum != joinNum) {
              flag = false;
              message = '分支和聚合节点的数量必须相同!';
            }
            //节点必须连线
            if (nodeName.length > 0) {
              flag = false;
              message = '请检查' + nodeName.join('、') + '节点的连线!';
            }
          } else {
            flag = false;
            message = '请配置流程图!';
          }
        }

        if (!flag && isNotEmpty(message)) {
          Modal.alert(message, 'error');
        }
        return flag;
      };

      //改变连线样式
      const updateLineStyle = (data) => {
        const $editor = editor.value.$editor;
        // 改变label
        $editor.graph.setCellStyles(data.type, data.value);
      };

      //给后台传参数据封装
      const getParams = () => {
        const metaInfo = cloneDeep(props.jebpmData);
        // 处理null数据变为''
        if (isEmpty(metaInfo.properties.startupSettings.canEveryoneRolesId)) {
          metaInfo.properties.startupSettings.canEveryoneRolesId = '';
          metaInfo.properties.startupSettings.canEveryoneRolesName = '';
        }

        const datas = { metaInfo: encode(metaInfo), metaInfoXml: '' };

        //获得图形的xml
        const mxgraph = editor.value.mxgraph;
        const encoder = new mxgraph.mxCodec();
        const node = encoder.encode(editor.value.$editor.graph.getModel());
        const xml = mxgraph.mxUtils.getPrettyXml(node);
        datas.metaInfoXml = encodeURIComponent(xml);

        const processBasicConfig = props.jebpmData.properties.processBasicConfig;
        const beanData = {
          tableCode: 'JE_WORKFLOW_PROCESSINFO',
          //产品Id
          SY_PRODUCT_ID: processBasicConfig.SY_PRODUCT_ID,
          //产品编码
          SY_PRODUCT_CODE: processBasicConfig.SY_PRODUCT_CODE,
          //产品名称
          SY_PRODUCT_NAME: processBasicConfig.SY_PRODUCT_NAME,
          //流程名称
          PROCESSINFO_NAME: processBasicConfig.name,
          //部署环境
          PROCESSINFO_DEPLOYMENT_ENVIRONMENT: processBasicConfig.deploymentEnvironment,
          //功能编码
          PROCESSINFO_FUNC_CODE: processBasicConfig.funcCode,
          //功能名称
          PROCESSINFO_FUNC_NAME: processBasicConfig.funcName,
          //功能Id
          PROCESSINFO_FUNC_ID: processBasicConfig.funcId,
          //流程分类名称
          PROCESSINFO_TYPE_NAME: processBasicConfig.processClassificationName,
          //流程分类编码
          PROCESSINFO_TYPE_CODE: processBasicConfig.processClassificationCode,
          //内容模板
          PROCESSINFO_CONTENT_TEMPLATE: processBasicConfig.contentModule,
          //附属功能名称
          PROCESSINFO_ATTACHED_FUNC_NAMES: processBasicConfig.attachedFuncNames,
          //附属功能编码
          PROCESSINFO_ATTACHED_FUNC_CODES: processBasicConfig.attachedFuncCodes,
          //附属功能Id
          PROCESSINFO_ATTACHED_FUNC_IDS: processBasicConfig.attachedFuncIds,
        };
        const JE_WORKFLOW_PROCESSINFO_ID = props.jebpmData.properties.JE_WORKFLOW_PROCESSINFO_ID;
        if (isNotEmpty(JE_WORKFLOW_PROCESSINFO_ID)) {
          beanData.JE_WORKFLOW_PROCESSINFO_ID = JE_WORKFLOW_PROCESSINFO_ID;
        }
        Object.assign(datas, beanData);
        return datas;
      };

      //导入操作
      const onImport = () => {
        //主键id
        const pkValue = props.jebpmData.properties.JE_WORKFLOW_PROCESSINFO_ID || '';
        //uuid
        const uuid = props.jebpmData.properties.process_id || '';
        /*  */
        SelectWindow.show({
          title: '导入流程',
          type: 'grid',

          // showButton: false,// 隐藏操作按钮
          configInfo: 'JE_WORKFLOW_PROCESSINFO,,,S',
          callback: function ({ rows, config, $modal }) {
            if (rows && rows.length > 0) {
              const id = rows[0].JE_WORKFLOW_PROCESSINFO_ID;
              getInfoById({ pkValue: id, tableCode: 'JE_WORKFLOW_PROCESSINFO' })
                .then((data) => {
                  const metaInfo = data.data.metaInfo;
                  const metaInfoXml = data.data.metaInfoXml;
                  //回显主数据
                  // props.jebpmData.initData(decode(metaInfo), id);
                  emit('loadData', decode(metaInfo), pkValue, isEmpty(uuid) ? 'new' : uuid);
                  //回显流程图
                  setWorkFlowChart(metaInfoXml);
                })
                .catch((error) => {
                  Modal.alert(error.message, 'error');
                });
            }
          },
        });
      };

      const editorXml = ref('');

      //回显流程图
      const setWorkFlowChart = (data, type) => {
        if (type == 'init') {
          editorXml.value = data;
        } else {
          const xml = decodeURIComponent(data);
          const mxgraph = editor.value.mxgraph;
          const doc = mxgraph.mxUtils.parseXml(xml);
          const codec = new mxgraph.mxCodec(doc);
          codec.decode(doc.documentElement, editor.value.$editor.graph.getModel());
        }
      };

      //打印操作
      const onPrint = () => {
        const $editorUi = editor.value.$editorUi;
        const $PrintDialog = editor.value.$PrintDialog;
        let printDialog = null;
        if (isEmpty(printDialog)) {
          printDialog = new $PrintDialog($editorUi, '打印');
        }
        if (isNotEmpty(printDialog)) {
          printDialog.preview(true);
        }
      };

      //移动方法
      const onMove = (type) => {
        const $editor = editor.value.$editor;
        $editor.graph.alignCells(type);
      };

      //缩放
      const onZoom = (type) => {
        const $editor = editor.value.$editor;
        //放大
        if (type == 'up') {
          $editor.graph.zoomIn();
          //缩小
        } else if (type == 'down') {
          $editor.graph.zoomOut();
          //正常
        } else {
          $editor.graph.zoomTo(1);
        }
      };

      //缩略图
      const onThumbnail = () => {
        const outlineDom = document.getElementsByClassName('editor-outline')[0];
        outlineDom.style.display = 'block';
        const outlineContextDom = document.getElementsByClassName('editor-outline-context')[0];
        new editor.value.$outline(editor.value.$editor.graph, outlineContextDom);
      };

      //向前向后方法
      const onLocation = (type) => {
        const $editorUi = editor.value.$editorUi;
        if (type == 'toFront') {
          $editorUi.actions.actions.toFront.funct();
        } else if (type == 'toBack') {
          $editorUi.actions.actions.toBack.funct();
        }
      };

      //隐藏提示窗口
      const doHideTooltip = () => {
        const tooltipDoms = document.getElementsByClassName('ant-tooltip');
        if (tooltipDoms.length > 0) {
          for (let index = 0; index < tooltipDoms.length; index++) {
            const element = tooltipDoms[index];
            element.style.display = 'none';
          }
        }
      };

      return {
        buttonArray,
        handlerBtn,
        options: { top: { size: 40 } },
        onSave,
        editor,
        value,
        language,
        onNodeChange,
        onNodeLabelChange,
        onNodeRemove,
        saveDisable,
        onImport,
        setWorkFlowChart,
        editorXml,
        onPrint,
        onMove,
        onZoom,
        onThumbnail,
        onLocation,
        updateNodeLabel,
        updateLineStyle,
      };
    },
  });
</script>

<style lang="less" scoped>
  .workflow-design {
    border-right: 1px solid #e6e6e6;
    .design-panel {
      background: url()
        repeat !important;
      padding: 20px;
    }
    .btn {
      width: 80px !important;
      height: 32px !important;
      line-height: 32px;
      text-align: center;
      background: #3265f5;
      cursor: pointer;
      margin-top: 18px;
      color: #ffffff;
      font-size: 14px;
      border-radius: 2px;
      &:hover {
        background: #5c8dff;
      }
    }
  }
</style>
<style lang="less">
  .workflow-design {
    .je-editor-draw .ant-collapse-content > .ant-collapse-content-box {
      padding: 0 !important;
    }
  }
</style>
